# 导入sys模块
import sys
# 导入datetime用于获取当前时间
from datetime import datetime
# 导入defaultdict用于统计日志数量
from collections import defaultdict

# 定义智能日志系统类
class SmartLogger:
    # 类文档字符串
    """智能日志系统"""
    
    # 定义日志级别常量
    DEBUG = 10
    INFO = 20
    WARNING = 30
    ERROR = 40
    CRITICAL = 50
    
    # 定义日志级别与名称的映射
    LEVEL_NAMES = {
        DEBUG: 'DEBUG',
        INFO: 'INFO',
        WARNING: 'WARNING',
        ERROR: 'ERROR',
        CRITICAL: 'CRITICAL'
    }
    
    # 定义ANSI颜色代码
    COLORS = {
        'DEBUG': '\033[94m',      # 蓝色
        'INFO': '\033[92m',       # 绿色
        'WARNING': '\033[93m',    # 黄色
        'ERROR': '\033[91m',      # 红色
        'CRITICAL': '\033[95m',   # 紫色
        'RESET': '\033[0m'        # 重置
    }
    
    # 初始化方法
    def __init__(self, name='Logger', level=DEBUG, log_file=None):
        """
        初始化日志系统
        
        参数:
            name: 日志器名称
            level: 最低日志级别
            log_file: 日志文件路径（可选）
        """
        # 设置日志器名称
        self.name = name
        # 设置最低日志级别
        self.level = level
        # 初始化日志文件路径为None
        self.log_file = None
        # 初始化文件句柄为None
        self.file_handle = None
        # 初始化日志统计字典
        self.stats = defaultdict(int)  # 统计各级别日志数量
        
        # 如果指定了日志文件，打开它
        if log_file:
            # 设置日志文件路径
            self.log_file = log_file
            # 以追加模式打开日志文件，编码为utf-8
            self.file_handle = open(log_file, 'a', encoding='utf-8')
    
    # 上下文管理器进入方法
    def __enter__(self):
        """进入上下文管理器"""
        # 返回自身
        return self
    
    # 上下文管理器退出方法
    def __exit__(self, exc_type, exc_val, exc_tb):
        """退出上下文管理器，自动关闭文件"""
        # 如果有打开的文件句柄，关闭文件
        if self.file_handle:
            self.file_handle.close()
        # 返回False，不屏蔽异常
        return False
    
    # 内部日志记录方法
    def _log(self, level, *args):
        """
        内部日志方法
        
        参数:
            level: 日志级别
            *args: 要打印的内容
        """
        # 如果日志级别低于设置的最低级别，不输出
        if level < self.level:
            return
        
        # 获取日志级别名称
        level_name = self.LEVEL_NAMES.get(level, 'UNKNOWN')
        # 获取对应颜色代码
        color = self.COLORS.get(level_name, '')
        # 获取重置颜色代码
        reset = self.COLORS['RESET']
        
        # 获取当前时间戳
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        
        # 拼接日志消息内容
        message = ' '.join(str(arg) for arg in args)
        
        # 彩色输出到屏幕
        print(f"{color}[{level_name}] {timestamp} - {message}{reset}")
        
        # 如果有日志文件，输出到文件（无颜色）
        if self.file_handle:
            print(f"[{level_name}] {timestamp} - {message}", file=self.file_handle)
            # 立即刷新文件缓冲区
            self.file_handle.flush()
        
        # 统计该级别日志数量加一
        self.stats[level_name] += 1
    
    # 记录DEBUG级别日志
    def debug(self, *args):
        """DEBUG级别日志"""
        self._log(self.DEBUG, *args)
    
    # 记录INFO级别日志
    def info(self, *args):
        """INFO级别日志"""
        self._log(self.INFO, *args)
    
    # 记录WARNING级别日志
    def warning(self, *args):
        """WARNING级别日志"""
        self._log(self.WARNING, *args)
    
    # 记录ERROR级别日志
    def error(self, *args):
        """ERROR级别日志"""
        self._log(self.ERROR, *args)
    
    # 记录CRITICAL级别日志
    def critical(self, *args):
        """CRITICAL级别日志"""
        self._log(self.CRITICAL, *args)
    
    # 打印格式化表格方法
    def print_table(self, headers, rows):
        """
        打印格式化的表格
        
        参数:
            headers: 表头列表
            rows: 数据行列表（每行是一个列表）
        """
        # 计算每列的最大宽度
        col_widths = []
        for i, header in enumerate(headers):
            # 以表头长度为初始最大宽度
            max_width = len(str(header))
            # 遍历每一行，更新最大宽度
            for row in rows:
                if i < len(row):
                    max_width = max(max_width, len(str(row[i])))
            # 每列宽度加2，留出额外空间
            col_widths.append(max_width + 2)  # 额外空间
        
        # 打印表头
        header_line = ''.join(f"{str(h):<{w}}" for h, w in zip(headers, col_widths))
        print(header_line)
        # 打印分隔线
        print('-' * sum(col_widths))
        
        # 打印数据行
        for row in rows:
            row_line = ''.join(f"{str(cell):<{w}}" for cell, w in zip(row, col_widths))
            print(row_line)
    
    # 显示日志统计报告方法
    def show_statistics(self):
        """显示日志统计报告"""
        # 打印标题分隔线
        print("\n" + "=" * 40)
        # 打印报告标题
        print(f"{'日志统计报告':^38}")
        # 打印标题分隔线
        print("=" * 40)
        
        # 计算所有日志的总数
        total = sum(self.stats.values())
        # 如果没有日志记录，提示并返回
        if total == 0:
            print("暂无日志记录")
            print("=" * 40)
            return
        
        # 定义表头
        headers = ['级别', '数量', '占比']
        # 初始化数据行
        rows = []
        
        # 按级别统计日志数量和占比
        for level_name in ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']:
            count = self.stats.get(level_name, 0)
            percentage = (count / total * 100) if total > 0 else 0
            rows.append([level_name, count, f"{percentage:.1f}%"])
        
        # 添加总计行
        rows.append(['总计', total, '100.0%'])
        
        # 打印表格
        self.print_table(headers, rows)
        # 打印结束分隔线
        print("=" * 40)


# 使用示例函数
def test_logger():
    """测试日志系统"""
    # 使用上下文管理器，自动关闭文件
    with SmartLogger('TestApp', level=SmartLogger.DEBUG, log_file='app.log') as logger:
        # 记录各种级别的日志
        logger.debug("开始处理数据")
        logger.info("数据处理成功")
        logger.info("用户登录", "用户ID: 12345")
        logger.warning("磁盘空间不足")
        logger.error("文件读取失败")
        logger.critical("系统崩溃")
        
        # 多条日志
        for i in range(5):
            logger.debug(f"调试信息 {i}")
            logger.info(f"普通信息 {i}")
        
        # 打印自定义表格
        print("\n用户列表:")
        headers = ['用户名', '年龄', '城市']
        rows = [
            ['张三', 25, '北京'],
            ['李四', 30, '上海'],
            ['王五', 28, '深圳']
        ]
        logger.print_table(headers, rows)
        
        # 显示统计报告
        logger.show_statistics()


# 运行测试
if __name__ == '__main__':
    # 调用测试函数
    test_logger()